本篇擷取重點:
這篇"無法"要告訴大家,泛型處理常式(.ashx)是什麼或是關於他的底層學理,因為我也還看不懂嗚嗚嗚嗚,只能提供一個使用範例及大概使用的方向,讓大家也許在需要用時能夠暫時應急應急,但正確觀念的確立及其底層學理的意義,就需要讀者再去翻翻書或看其他大大的文章。
一、泛型處理常式(.ashx)及ASPX在使用上的粗略比較
泛型處理常式(.ashx)與ASPX皆可當作httphandler来使用,他們在使用上的差異在於:
使用條件上,ASPX較強調使用者及後端之間的互動性,而(.ashx)則多用來處理無須顯示頁面且無須持續來回處理互動的部分,例如同一頁面中進行動態的圖片展示或連接資料庫比對帳號是否重複...等。
也有人說,「(.ashx)就是沒有畫面的ASPX」,例如,檔案下載服務,透過傳遞參數給.ashx,來決定要下載那一個檔案,這個下載的動作是不需UI畫面的。又或者,提供給AJAX上傳檔案用.ashx,因為AJAX來上傳檔案,接收端的.ashx是不需要UI畫面。
參考資料:
https://blog.csdn.net/thinker28754/article/details/4552040
https://blog.kkbruce.net/2013/12/.ashx-vs-aspnet-web-api.html#.XZBeTEYzZEY
二、如何新增泛型處理常式
檔案總管 - 專案 - 滑鼠右鍵 - 加入 - 新增項目
選擇泛型處理常式 - 命名 - 確定
預設內容
三、瀏覽上傳圖片的範例
在設計頁面(.aspx)拖引出所需的工具箱控制項,
<form id="form1" runat="server">
<div>
<asp:FileUpload runat="server" ID="FileUpload1" />
<asp:Button Text="Click" ID="Button1" UseSubmitBehavior="false" runat="server" OnClick="Button_Click" />
<asp:Label ID="Message" runat="server" Text=""></asp:Label>
<br />
<asp:Image runat="server" ID="Image1" />
</div>
</form>
後置程式碼部分(.aspx.cs)分為兩部分,
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
}
}
protected void Button_Click(object sender, EventArgs e)
{
// 存入session
if (FileUpload1.PostedFile != null)
{
HttpPostedFile myFile = FileUpload1.PostedFile;
Session["myFile"] = myFile;
// Set ImageUrl
Image1.ImageUrl = "Handler1.ashx";
}
//存入伺服器中
string fileName;
if (FileUpload1.HasFile)
{
if (FileUpload1.PostedFile.ContentType.IndexOf("image") == -1)
{
Message.Text = "檔案型態錯誤!";
return;
}
//取得副檔名
string Extension = FileUpload1.FileName.Split('.')[FileUpload1.FileName.Split('.').Length - 1];
//新檔案名稱
fileName = String.Format("{0:yyyyMMddhhmmsss}.{1}", DateTime.Now, Extension);
//上傳目錄為/Images/
FileUpload1.SaveAs(Server.MapPath(String.Format("~/images/{0}", fileName)));
//
}
else
{
Message.Text = "沒有上傳檔案";
return;
}
}
在(.ashx)中,使用session有兩個重點:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.SessionState; //因為有使用到session,故須引用
namespace ShareTwo
{
/// <summary>
/// Handler1 的摘要描述
/// </summary>
public class Handler1 : IHttpHandler, IRequiresSessionState //因為有使用到session
{
public void ProcessRequest(HttpContext context)
{
if (context.Session["myFile"] != null)
{
HttpPostedFile myFile = (HttpPostedFile)context.Session["myFile"];
int myFile_Length = myFile.ContentLength;
//設定緩衝區大小
byte[] myData = new byte[myFile_Length];
//myFile檔案的內容讀取到位元組陣列
myFile.InputStream.Read(myData, 0, myFile_Length);
context.Response.Clear();
//告訴瀏覽器檔案為image/jpeg的MIME類型
context.Response.ContentType = "image/jpeg";
//將二進位字元的字串寫入 HTTP 輸出資料流
context.Response.BinaryWrite(myData);
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
顯示頁面的上傳圖檔預覽
參考資料:
https://blog.miniasp.com/post/2008/03/09/Using-contextSession-object-in-HttpHandler
https://dotblogs.com.tw/mis2000lab/archive/2013/08/20/ashx_beginner_02_fileupload_picture_preview.aspx
此篇內容整理自多篇網路文章、PPT及自己的理解,但筆者也仍處在初階的學習過程,對程式概念的理解及判斷都尚不足,若有錯誤的地方,也煩請各位大大提點,先謝謝大家惹!!
ashx不難懂,因為System.Web.UI.Page類別本身就是一個很大號的ashx (HTTP Handler),只是它在web.config中被設定對應.aspx由它來處理而己,這也就是說HTTP Handler可以改掉原本的副檔名 (只要在web.config登錄),而IIS/aspnet_wp.exe會將要求導向到指定的HTTP Handler,這時程式就可以接手處理,可得到完整的要求內容,並且要自己輸出回應的資料 (aspx是回應HTML),也就是說即便是ashx一樣可以產生畫面,只要自己組出必要的HTML的話。
ashx所要賦與的是程式開發上的彈性,而且不用受到Web Form Page Lifecycle那麼多的動作影響,輸出又可以自己決定,速度也會比aspx要快 (因為沒有走Page Lifecycle),但缺點 (也是優點) 就是所有的輸出,包含類型 (ContentType) 以及內容 (Content) 都要自己處理輸出,這樣更看出程式員對.NET Framework的熟悉度了。
PS: 文中的範例實務上一般不會這樣做,因為將檔案放在Session是很耗記憶體的作法,實務上的作法多半是寫入一個暫存檔,ashx再去讀這個暫存檔,這樣就只會耗磁碟空間,磁碟的價格比記憶體便宜太多了。
好的,謝謝朱大的詳細講解,我再研究一下暫存檔,我好像還沒碰過XDDD